package discover

import (
	"context"
	"fmt"
	"time"

	"github.com/lukeaxu/discover/registry"
	"google.golang.org/grpc/resolver"
)

type grpcResolverBuilder struct {
	registry registry.Registry
	timeout  time.Duration
}

func NewGrpcResolverBuilder(r registry.Registry, d time.Duration) (*grpcResolverBuilder, error) {
	return &grpcResolverBuilder{
		registry: r,
		timeout:  d,
	}, nil
}

func (rb *grpcResolverBuilder) Build(target resolver.Target,
	cc resolver.ClientConn, opts resolver.BuildOptions) (resolver.Resolver, error) {
	r := &grpcResolver{
		cc:       cc,
		registry: rb.registry,
		target:   target,
		timeout:  rb.timeout,
	}
	r.ResolveNow(resolver.ResolveNowOptions{})

	ctx, cancel := context.WithCancel(context.Background())
	eventChann, err := rb.registry.Subscribe(ctx, target.Endpoint())
	if err != nil {
		cc.ReportError(err)
		cancel()
		return nil, err
	}
	go func() {
		select {
		case <-eventChann:
			r.resolveNow()
		case <-r.close:
			cancel()
			return
		}
	}()

	return r, nil
}

func (rb *grpcResolverBuilder) Scheme() string {
	return "registry"
}

func (rb *grpcResolverBuilder) targetForServiceName(sn string) string {
	return fmt.Sprintf("%s:///%s", rb.Scheme(), sn)
}
